package com.nandasoft.njuerp.common.dao;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.stereotype.Component;



@Component
public class BaseDao<T>
{

	@Autowired
	protected NamedParameterJdbcTemplate namedParameterJdbcTemplate;
	public static Logger log = Logger.getLogger(BaseDao.class);

	/**
	 * 增加记录
	 * 
	 * @param sql
	 * insert sql
	 * @param paramSource
	 */
	public int insert(String sql, SqlParameterSource paramSource)
	{
		int i = 1;
		try
		{
			i = this.namedParameterJdbcTemplate.update(sql, paramSource);
		}
		catch (DuplicateKeyException e)
		{
			e.printStackTrace();
			throw new SQLOperationException("mismatch unique constraint");
		}
		catch (DataIntegrityViolationException e)
		{
			e.printStackTrace();
			throw new SQLOperationException("mismatch data integrity");
		}
		return i;
	}

	/**
	 * 增加记录
	 * 
	 * @param sql
	 * @param paramMap
	 */
	public int insert(String sql, Map<String, ?> paramMap)
	{
		int i = 1;
		try
		{
			i = this.namedParameterJdbcTemplate.update(sql, paramMap);
		}
		catch (DuplicateKeyException e)
		{
			throw new SQLOperationException("mismatch unique constraint");
		}
		catch (DataIntegrityViolationException e)
		{
			throw new SQLOperationException("mismatch data integrity");
		}
		return i;
	}

	/**
	 * 获取对象
	 * 
	 * @param sql
	 * @param ps
	 * @param clazz
	 * @return
	 */
	public T queryEntity(String sql, SqlParameterSource ps, Class<T> clazz)
	{

		return namedParameterJdbcTemplate.queryForObject(sql, ps,
				new BeanPropertyRowMapper<T>(clazz));

	}

	/**
	 * 获取对象
	 * 
	 * @param sql
	 * @param ps
	 * @param clazz
	 * @return
	 */
	public T queryEntity(String sql, Map<String, ?> ps, Class<T> clazz)
	{

		return namedParameterJdbcTemplate.queryForObject(sql, ps,new BeanPropertyRowMapper<T>(clazz));

	}

	public T queryEntity(String sql, SqlParameterSource ps,
			RowMapper<T> rowMapper)
	{
		try
		{
			return namedParameterJdbcTemplate.queryForObject(sql, ps, rowMapper);
		}
		catch (EmptyResultDataAccessException e)
		{
			return null;
		}

	}

	public T queryEntity(String sql, Map<String, ?> ps, RowMapper<T> rowMapper)
	{
		try
		{
			return namedParameterJdbcTemplate.queryForObject(sql, ps, rowMapper);
		}
		catch (EmptyResultDataAccessException e)
		{
			return null;
		}
	}

	public int update(String sql, Map<String, ?> ps)
	{
		int i = 1;
		try
		{
			i = this.namedParameterJdbcTemplate.update(sql, ps);
		}
		catch (DuplicateKeyException e)
		{
			throw new SQLOperationException("mismatch unique constraint");
		}
		catch (DataIntegrityViolationException e)
		{
			throw new SQLOperationException("dataIntegrityViolationException constraint");
		}
		return i;
	}

	public int update(String sql, SqlParameterSource ps)
	{
		int i = 1;
		try
		{
			i = this.namedParameterJdbcTemplate.update(sql, ps);
		}
		catch (DuplicateKeyException e)
		{
			throw new SQLOperationException("mismatch unique constraint");
		}
		catch (DataIntegrityViolationException e)
		{
			e.printStackTrace();
			// throw new
			// SQLOperationException("  dataIntegrityViolationException   constraint");
		}
		return i;
	}

	public int delete(String sql, SqlParameterSource ps)
	{
		return this.namedParameterJdbcTemplate.update(sql, ps);
	}

	public int delete(String sql, Map<String, ?> ps)
	{
		return this.namedParameterJdbcTemplate.update(sql, ps);
	}

	public List<T> queryForList(String sql, Map<String, ?> ps,
			RowMapper<T> rowMapper)
	{
		return this.namedParameterJdbcTemplate.query(sql, ps, rowMapper);
	}

	public List<T> queryForList(String sql, SqlParameterSource ps,
			RowMapper<T> rowMapper)
	{
		return this.namedParameterJdbcTemplate.query(sql, ps, rowMapper);
	}

	protected int queryCount(String sql, Map<String, ?> ps)
	{
		if (ps == null)
		{
			ps = new HashMap<String, Object>();
		}
		return this.namedParameterJdbcTemplate.queryForInt(sql, ps);
	}

	protected Object queryObject(String sql, HashMap<String, Object> hashMap)
	{
		Object obj = null;
		if (sql != null)
		{
			List list = this.namedParameterJdbcTemplate.queryForList(sql,hashMap);
			if (null != list)
			{
				obj = list.get(0);
			}
		}
		return obj;
	}

	protected long queryLongCount(String sql, Map<String, ?> ps)
	{
		if (ps == null)
		{
			ps = new HashMap<String, Object>();
		}
		return this.namedParameterJdbcTemplate.queryForLong(sql, ps);
	}

	protected int queryCountByTableName(String tableName)
	{
		String sql = "SELECT count(t.objid) FROM " + tableName
				+ " t WHERE 1=1";
		Map<String, Object> params = new HashMap<String, Object>();
		return queryCount(sql, params);
	}

	/*
	 * protected List<T> queryBypage(String sql, Map<String, Object> ps, int
	 * start, int limit, RowMapper<T> rowMapper) { sql +=
	 * " limit :startIndex,:limit"; if (ps == null) { ps = new HashMap<String,
	 * Object>(); } ps.put("startIndex", start); ps.put("limit", limit); return
	 * queryForList(sql, ps, rowMapper); }
	 */

	protected List<T> queryBypage(String sql, Map<String, Object> ps,
			int start, int limit, RowMapper<T> rowMapper)
	{
		int startCount = (start - 1) * limit + 1;
		int end = start * limit;
		sql = "SELECT * FROM ( SELECT A.*, ROWNUM RN FROM (" + sql
				+ ") A WHERE ROWNUM <= " + end + ") WHERE RN >=" + startCount;
		log.debug(sql);
		/*
		 * if (ps == null) { ps = new HashMap<String, Object>(); }
		 * ps.put("startIndex", start); ps.put("limit", limit);
		 */
		return queryForList(sql, ps, rowMapper);
	}

	private Object invokeMethod(Object owner, String methodName, Object[] args)
			throws Exception
	{
		Class ownerClass = owner.getClass();
		methodName = methodName.substring(0, 1).toUpperCase()
				+ methodName.substring(1);
		Method method = null;
		try
		{
			method = ownerClass.getMethod("get" + methodName);
		}
		catch (SecurityException e)
		{
		}
		catch (NoSuchMethodException e)
		{
			return " can't find 'get" + methodName + "' method";
		}
		if(method != null){
			return method.invoke(owner);
		}else{
			return null;
		}
		
	}

	protected String getUpdateSql(Object obj, String sql, Class cls,String... exclude)
	{
		Field field[] = cls.getDeclaredFields();
		for (Field f : field)
		{
			try
			{
				Object v = invokeMethod(obj, f.getName(), null);
				log.debug("属性:" + f.getName() + "\t" + v + "\t" + f.getType());
				log.debug("修改前sql:" + sql);
				if (v == null)
				{
					if (exclude != null)
					{

					}
					sql = sql.replace(f.getName() + "=:" + f.getName() + ",",
							"");
					log.debug("修改后sql:" + sql);
				}
			}
			catch (Exception e)
			{

			}
		}
		return sql;
	}

	public List<Map<String, Object>> queryForList(String sql,Map<String, Object> paramMap)
	{
		List<Map<String, Object>> li = namedParameterJdbcTemplate.queryForList(sql, paramMap);
		log.debug("共查到"+li.size()+"条记录");
		return li;
	}
}

